package com.jerry.immutableobject;

import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

public class IntegerAccumulator {

    private final  int init;

    public IntegerAccumulator(int init) {
        this.init = init;
    }

    public IntegerAccumulator(IntegerAccumulator integerAccumulator, int init) {
        this.init = integerAccumulator.getValue() + init;
    }

    public IntegerAccumulator add(int i) {
        //每回新增都创建一个新的对象，将每回执行的结果与原有的对象进行剥离。从而实现多个线程虽然操作同一个对象，但执行的结果不对原有对象产生影响，从而保证了原有对象的不可以变性，达到个线程执行效果的互不干扰
        //这里只是介绍一种实现保证对象可以不被线程改变的方式，在某些场景下，需要我们将基础参数作为多个线程计算的入参进行共享。
        return new IntegerAccumulator(this, i);
    }

    public int getValue() {
        return this.init;
    }

    private static void slowly() {

        try {
            TimeUnit.MILLISECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        IntegerAccumulator accumulator = new IntegerAccumulator(0);
        IntStream.range(0, 3).forEach(i -> new Thread(() -> {
            int inc = 0;

            while (true) {
                int oldValue = accumulator.getValue();
                int result = accumulator.add(inc).getValue();
                System.out.println(oldValue+"+"+inc+" result is "+result);
                if (inc + oldValue != result) {

                    System.err.println("ERROR:" + oldValue + "+" + inc + "=" + result);
                }
                inc++;
                slowly();
            }
        }).start());
    }
}
